package cn.piggy.gateway.center.domain.nginx.service;

import cn.piggy.gateway.center.domain.nginx.model.aggregates.NginxConfig;
import cn.piggy.gateway.center.domain.nginx.model.vo.LocationVO;
import cn.piggy.gateway.center.domain.nginx.model.vo.UpstreamVO;
import com.google.common.base.Joiner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.*;
import java.util.ArrayList;
import java.util.List;


@Service
public class LoadBalancingService extends AbstractLoadBalancing {

    private Logger logger = LoggerFactory.getLogger(LoadBalancingService.class);

    @Value("${nginx.server_name}")
    private String nginx_server_name;

    @Override
    protected String createNginxConfigFile(NginxConfig nginxConfig) throws IOException {
        // 创建文件
        String nginxConfigContentStr = buildNginxConfig(nginxConfig.getUpstreamList(), nginxConfig.getLocationList());
        File file = new File("D:/program/nginx/nginx-1.23.4/conf/nginx.conf");
        if (!file.exists()) {
            boolean success = file.createNewFile();
            if (success) {
                logger.info("nginx.conf file created successfully.");
            } else {
                logger.info("nginx.conf file already exists.");
            }
        }
        // 写入内容
        // todo 方便调试
//        FileWriter writer = new FileWriter(file);
//        writer.write(nginxConfigContentStr);
//        writer.close();
        // 返回结果
        return file.getAbsolutePath();
    }

    @Override
    protected void refreshNginxConfigLinux() {}

    @Override
    protected void refreshNginxConfigWindows() {
        try {
            List<String> cmdList = new ArrayList<>();
            cmdList.add("cd /program/nginx/nginx-1.23.4");
            cmdList.add("nginx.exe -s reload");
            String cmdBin = "cmd /c ";
            String cmdStr = Joiner.on("&&").join(cmdList);
            Process process = Runtime.getRuntime().exec(cmdBin + cmdStr);
            process.destroy();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String buildNginxConfig(List<UpstreamVO> upstreamList, List<LocationVO> locationList) {
        String config = "\n" +
                "#user  nobody;\n" +
                "worker_processes  1;\n" +
                "\n" +
                "#error_log  logs/error.log  notice;\n" +
                "#pid        logs/nginx.pid;\n" +
                "\n" +
                "\n" +
                "events {\n" +
                "    worker_connections  1024;\n" +
                "}\n" +
                "\n" +
                "\n" +
                "http {\n" +
                "    include       mime.types;\n" +
                "    default_type  application/octet-stream;\n" +
                "\n" +
                "    log_format  main  '$remote_addr - $remote_user [$time_local] \"$request\" '\n" +
                "                      '$status $body_bytes_sent \"$http_referer\" '\n" +
                "                      '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n" +
                "\n" +
                "    #access_log  logs/access.log  main;\n" +
                "\n" +
                "    sendfile        on;\n" +
                "    #tcp_nopush     on;\n" +
                "\n" +
                "    keepalive_timeout  65;\n" +
                "\n" +
                "    #gzip  on;\n" +
                "\n" +
                "\n" +
                "upstream_config_placeholder" +
                "\n" +
                "    # HTTP服务器\n" +
                "    server {\n" +
                "        # 监听80端口，用于HTTP协议\n" +
                "        listen  80;\n" +
                "\n" +
                "        # 定义使用IP/域名访问\n" +
                "        server_name "+nginx_server_name+";\n" +
                "\n" +
                "        location / {\n" +
                "            root   html;\n" +
                "            index  index.html index.htm;\n" +
                "        }\n" +
                "\n" +
                "        # 反向代理的路径（upstream绑定），location 后面设置映射的路径\n" +
                "        # location / {\n" +
                "        #    proxy_pass http://127.0.0.1:xxxx;\n" +
                "        # }\n" +
                "\n" +
                "        location /piggy {\n" +
                "            proxy_pass http://127.0.0.1:7397;\n" +
                "        }\n" +
                "\n" +
                "location_config_placeholder" +
                "    }\n" +
                "}\n";

        // 组装配置 Upstream
        StringBuilder upstreamStr = new StringBuilder();
        for (UpstreamVO upstream : upstreamList) {
            upstreamStr.append("\t").append("upstream").append(" ").append(upstream.getName()).append(" {\r\n");
            upstreamStr.append("\t").append("\t").append(upstream.getStrategy()).append("\r\n");
            List<String> servers = upstream.getServers();
            for (String server : servers) {
                upstreamStr.append("\t").append("\t").append("server").append(" ").append(server).append(";\r\n");
            }
            upstreamStr.append("\t").append("}").append("\r\n").append("\r\n");
        }

        // 组装配置 Location
        StringBuilder locationStr = new StringBuilder();
        for (LocationVO location : locationList) {
            // location /10001/
            locationStr.append("\t").append("\t").append("location").append(" ").append(location.getName()).append(" {\r\n");
            // rewrite ^/10001/(.*)$ /$1 break; 设置重写URL，在代理后去掉根路径 api01 此字段只是配合路由，不做处理
            locationStr.append("\t").append("\t").append("\t").append("rewrite ^").append(location.getName()).append("(.*)$ /$1 break;").append("\r\n");
            // proxy_pass http://10001;
            locationStr.append("\t").append("\t").append("\t").append("proxy_pass").append(" ").append(location.getProxyPass()).append("\r\n");
            locationStr.append("\t").append("\t").append("}").append("\r\n").append("\r\n");
        }

        // 替换配置
        config = config.replace("upstream_config_placeholder", upstreamStr.toString());
        config = config.replace("location_config_placeholder", locationStr.toString());
        return config;
    }

}
